package com.gepengjun.lims.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.gepengjun.lims.controler.UserController;
import com.gepengjun.lims.entity.Orgnazation;
import com.gepengjun.lims.entity.RefRoleUser;
import com.gepengjun.lims.entity.Role;
import com.gepengjun.lims.entity.User;
import com.gepengjun.lims.mapper.UserMapper;
import com.gepengjun.lims.service.OrgnazationService;
import com.gepengjun.lims.service.RefRoleUserService;
import com.gepengjun.lims.service.RoleService;
import com.gepengjun.lims.service.UserService;
import com.gepengjun.lims.service.impl.base.BaseUserServiceImpl;
import com.gepengjun.lims.util.xssf.XSSFUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.print.attribute.standard.NumberUp;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jun
 * @since 2018-08-19
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper , User> implements UserService {

    protected static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Resource
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;

    @Autowired
    private OrgnazationService orgnazationService;

    @Autowired
    private RefRoleUserService refRoleUserService;


    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insert(User var1){ return super.insert(var1); }

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertAllColumn(User var1){ return super.insertAllColumn(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertBatch(List<User> var1){ return super.insertBatch(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertBatch(List<User> var1, int var2){ return super.insertBatch(var1,var2);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertOrUpdateBatch(List<User> var1){ return super.insertOrUpdateBatch(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertOrUpdateBatch(List<User> var1, int var2){ return super.insertOrUpdateBatch(var1,var2);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertOrUpdateAllColumnBatch(List<User> var1){ return super.insertOrUpdateAllColumnBatch(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertOrUpdateAllColumnBatch(List<User> var1, int var2){ return super.insertOrUpdateAllColumnBatch(var1,var2);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean deleteById(Serializable var1){ return super.deleteById(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean deleteByMap(Map<String, Object> var1){ return super.deleteByMap(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean delete(Wrapper<User> var1){ return super.delete(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean deleteBatchIds(Collection<? extends Serializable> var1){ return super.deleteBatchIds(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean updateById(User var1){ return super.updateById(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean updateAllColumnById(User var1){ return super.updateAllColumnById(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean update(User var1, Wrapper<User> var2){ return super.update(var1,var2);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean updateForSet(String var1, Wrapper<User> var2){ return super.updateForSet(var1,var2);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean updateBatchById(List<User> var1){ return super.updateBatchById(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean updateBatchById(List<User> var1, int var2){ return super.updateBatchById(var1,var2);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean updateAllColumnBatchById(List<User> var1){ return super.updateAllColumnBatchById(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean updateAllColumnBatchById(List<User> var1, int var2){ return super.updateAllColumnBatchById(var1,var2);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertOrUpdate(User var1){ return super.insertOrUpdate(var1);}

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public boolean insertOrUpdateAllColumn(User var1){ return super.insertOrUpdateAllColumn(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public User selectById(Serializable var1){ return super.selectById(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public List<User> selectBatchIds(Collection<? extends Serializable> var1){ return super.selectBatchIds(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public List<User> selectByMap(Map<String, Object> var1){ return super.selectByMap(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public User selectOne(Wrapper<User> var1){ return super.selectOne(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public Map<String, Object> selectMap(Wrapper<User> var1){ return super.selectMap(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public Object selectObj(Wrapper<User> var1){ return super.selectObj(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public int selectCount(Wrapper<User> var1){ return super.selectCount(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public List<User> selectList(Wrapper<User> var1){ return super.selectList(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public Page<User> selectPage(Page<User> var1){ return super.selectPage(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public List<Map<String, Object>> selectMaps(Wrapper<User> var1){ return super.selectMaps(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public List<Object> selectObjs(Wrapper<User> var1){ return super.selectObjs(var1);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public Page<Map<String, Object>> selectMapsPage(Page var1, Wrapper<User> var2){ return super.selectMapsPage(var1,var2);}

    @Override
    @Cacheable(value = "user",keyGenerator = "myKeyGenerator")
    public Page<User> selectPage(Page<User> var1, Wrapper<User> var2){ return super.selectPage(var1,var2);}


    public List<User> findByUsernameAndPassword(String username, String passwordMd5){
        Map<String,Object> params = new HashMap<>();
        params.put("username",username);
        params.put("password",passwordMd5);
        return super.selectByMap(params);
    }

    @Override
    @CacheEvict(value = "user",allEntries = true)
    public Boolean updPassword(Long userId,String username, String password) {
        User user = new User();
        user.setUserId(userId);
        String salt = ((Object) new SimpleHash("MD5", username, username, 2)).toString();
        String passwordMd5 = ((Object) new SimpleHash("MD5", password, username + salt, 2)).toString();
        user.setSalt(salt);
        user.setPassword(passwordMd5);
        return super.updateById(user);
    }

    /**
     * 查找所有的用户
     * @param user
     * @param page
     * @return
     */
    @Override
    public Page<User> findUserPage(Page<User> page,User user) {
        logger.info("page.getCurrent()"+page.getCurrent());
        logger.info("page.getLimit()"+page.getLimit());
        List<User> userList = userMapper.findAllAvaibleUser(page,user);
        List<User> userList1 = new ArrayList<>();
        if (userList != null && userList.size() > 0){
            for (User user1:userList){
               logger.info("user1---"+user1);
                 /*
                Orgnazation dept = orgnazationService.findDeptByUserId(user1.getUserId());
                user1.setDept(dept);

                Map<String,Object> params = new HashMap<>();
                params.put("parent_id",dept.getParentId());
                */

                 Orgnazation dept = orgnazationService.selectById(user1.getOrgId());
                user1.setDept(dept);

                user1.setCompany(orgnazationService.selectById(dept.getParentId()));
                userList1.add(user1);
            }
        }
        page.setRecords(userList1);
        return page;
    }

    /**
     * 判断用户名是否可注册
     * @param username
     * @return
     */
    @Override
    public Boolean judgeUsernameAvailable(String username) {
        EntityWrapper<User> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("username",username);
        List<User> userList = super.selectList(entityWrapper);
        if (userList == null || userList.size() == 0){
            return true;
        }
        return false;
    }

    @Override
    @Transactional
    @CacheEvict(value = "user",allEntries = true)
    public Boolean addUser(User user,String roleIds) {
        String salt = ((Object) new SimpleHash("MD5", user.getUsername(), user.getUsername(), 2)).toString();
        String password = ((Object) new SimpleHash("MD5", "123456", user.getUsername() + salt, 2)).toString();
        user.setSalt(salt);
        user.setPassword(password);
        boolean flag = super.insert(user);
        logger.info("添加用户:flag:"+flag);
        if (flag){
            if (StringUtils.isNotEmpty(roleIds)){
                user = findByUsernameAndPassword(user.getUsername(),user.getPassword()).get(0);
                String[] roleIdArray = roleIds.split(",");
                for (int i = 0;i< roleIdArray.length;i++){
                    RefRoleUser refRoleUser = new RefRoleUser();
                    refRoleUser.setRoleId(Long.valueOf(roleIdArray[i]));
                    refRoleUser.setUserId(user.getUserId());
                    refRoleUserService.insert(refRoleUser);
                }
                return true;
            }

        }
        return false;
    }

    @Override
    @CacheEvict(value = "user",allEntries = true)
    public Boolean disableUser(User user) {
        user.setStatus(false);
        return super.updateById(user);
    }

    @Override
    @CacheEvict(value = "user",allEntries = true)
    public Boolean ableUser(User user) {
        user.setStatus(true);
        return super.updateById(user);
    }

    @Override
    @CacheEvict(value = "user",allEntries = true)
    public Boolean updUser(User user,String roleIds) {
        if (super.updateById(user)){
            Map<String,Object> params = new HashMap<>();
            params.put("user_id",user.getUserId());
            refRoleUserService.deleteByMap(params);
            if (StringUtils.isNotEmpty(roleIds)){
                String[] roleIdArray = roleIds.split(",");
                for (int i = 0 ;i < roleIdArray.length; i++){
                    RefRoleUser refRoleUser = new RefRoleUser();
                    refRoleUser.setUserId(user.getUserId());
                    refRoleUser.setRoleId(Long.valueOf(roleIdArray[i]));
                    refRoleUserService.insert(refRoleUser);
                }
            }
            return true;

        }
        return false;
    }

    @Override
    public  Map<String,Object> readFile(String filePath, String fileName) throws IOException{
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new FileInputStream(filePath+fileName));
        XSSFUtil xssfUtil = new XSSFUtil();
        DecimalFormat decimalFormat = new DecimalFormat("0");

        Sheet sheet =xssfWorkbook.getSheetAt(0);
        Map<String,Object> result = new HashMap<>();

        int maxRows = sheet.getPhysicalNumberOfRows();
        List<User> userList = new ArrayList<>();
        for (int i = 1;i < maxRows;i++){
            User user = new User();
            Row row = sheet.getRow(i);
            Cell usernameCell = row.getCell(0);
            String username = (String) xssfUtil.getCellValue(usernameCell);
            if (StringUtils.isNotEmpty(username)){
                String salt = ((Object)new SimpleHash("MD5",username,username,2)).toString();
                String password = ((Object)new SimpleHash("MD5","000000",salt,2)).toString();
                user.setSalt(salt);
                user.setPassword(password);
            }

            user.setUsername(username);
            Cell realNameCell = row.getCell(1);
            String realName = (String) xssfUtil.getCellValue(realNameCell);
            user.setRealName(realName);
            String telephone = xssfUtil.getCellValue(row.getCell(2)) == null?null:decimalFormat.format(xssfUtil.getCellValue(row.getCell(2)));
            user.setTelephone(telephone);

            user.setBirthday((Date) xssfUtil.getCellValue(row.getCell(3)));
            String sexString = (String) xssfUtil.getCellValue(row.getCell(4));

            Integer sex = 1;
            if (sexString != null && "男".equals(sexString)){
                sex = 1;
            }else if (sexString != null && "女".equals(sexString)){
                sex = 0;
            }
            user.setSex(sex);

            Cell orgIdCell = row.getCell(5);
            if (orgIdCell == null){
                user.setOrgId(null);
            }else {
                user.setOrgId((long)(double)xssfUtil.getCellValue(row.getCell(5)));
            }

            Double statusD = (Double) xssfUtil.getCellValue(row.getCell(6));
            if (statusD == null){
                user.setStatus(null);
            }else {
                String statusStr = String.valueOf(xssfUtil.getCellValue(row.getCell(6)));
                int status = 0;
                if (StringUtils.isEmpty(statusStr)){
                    user.setStatus(null);
                }else {
                    status = (int)(double)xssfUtil.getCellValue(row.getCell(6));

                }
                if (status == 1){
                    user.setStatus(true);
                }else {
                    user.setStatus(false);
                }
            }
            userList.add(user);
        }
        result.put("userList",userList);
        return result;
    }

    /**
     * 验证 批量导入的userList,有效性:用户名,部门编码,启用 是否为空;用户名是否有重复,是否可用;部门编码是否可用;
     * @param userList
     * @return
     */
    @Override
    public Map<String, String> validateUserAddList(List<User> userList) {
        Map<String,String> result = new HashMap<>();
        if (userList == null || userList.size() == 0){
            return result;
        }
        List<Orgnazation> deptList = orgnazationService.findAllAvailableDept();
        List<Long> deptIdList = new ArrayList<>();
        for (Orgnazation orgnazation:deptList){
            deptIdList.add(orgnazation.getOrgId());
        }
        logger.info(deptIdList.toString());
        List<Integer> unAvailableOrgIdRow = new ArrayList<>();


        Set<String> userNameSet = new HashSet<>();
        Set<Long> orgIdSet = new HashSet<>();

        List<Integer> userNameEmptyList = new ArrayList<>();
        List<Integer> userNameRepeatedList = new ArrayList<>();
        List<Integer> orgIdEmptyList = new ArrayList<>();

        List<Integer> statusEmptyList = new ArrayList<>();
        for (int i = 0; i < userList.size(); i++){
            User user = userList.get(i);
            if (StringUtils.isEmpty(user.getUsername())){
                userNameEmptyList.add(i+2);
            }else {

                if (!userNameSet.add(user.getUsername())){
                    userNameRepeatedList.add(i+2);
                }
            }

            if (user.getOrgId() ==null || StringUtils.isEmpty(user.getOrgId().toString())){
                orgIdEmptyList.add(i+2);
            }else {
                logger.info(String.valueOf(deptIdList.contains(user.getOrgId())));
                if (! deptIdList.contains(user.getOrgId())){
                    unAvailableOrgIdRow.add(i+2);
                }
            }

            if (user.getStatus() == null){
                statusEmptyList.add(i+2);
            }
        }
        if (userNameEmptyList.size() > 0){
            String userNameEmptyRow = "";
            for (int row:userNameEmptyList){
                userNameEmptyRow += (row + ",");
            }
            result.put("userNameEmptyRow",userNameEmptyRow.substring(0,userNameEmptyRow.length()-1));
        }
        if (userNameRepeatedList .size() > 0){
            String userNameRepeatedRow = "";
            for (int row:userNameRepeatedList){
                userNameRepeatedRow += row +",";
            }
            result.put("userNameRepeatedRow",userNameRepeatedRow.substring(0,userNameRepeatedRow.length()-1));
        }

        if (orgIdEmptyList .size() > 0){
            String orgIdEmptydRow = "";
            for (int row:orgIdEmptyList){
                orgIdEmptydRow += row +",";
            }
            result.put("orgIdEmptyList",orgIdEmptydRow.substring(0,orgIdEmptydRow.length()-1));
        }

        if (statusEmptyList .size() > 0){
            String statusEmptydRow = "";
            for (int row:statusEmptyList){
                statusEmptydRow += row +",";
            }
            result.put("statusEmptydRow",statusEmptydRow.substring(0,statusEmptydRow.length()-1));
        }





        List<String> signedUserNameList = new ArrayList<>();
        if (userNameSet.size() > 0){
            for (String username:userNameSet){
                if (!judgeUsernameAvailable(username)){
                    signedUserNameList.add(username);
                }
            }
        }

        if (signedUserNameList.size() > 0){
            String signedUserNames = "";
            for (String userName:signedUserNameList){
                signedUserNames += userName+",";
            }
            result.put("signedUserNames",signedUserNames.substring(0,signedUserNames.length()-1));
        }

        logger.info(unAvailableOrgIdRow.toString());
        if (unAvailableOrgIdRow.size() > 0){
            String unAvailableOrgRow = "";
            for (int row:unAvailableOrgIdRow){
                unAvailableOrgRow += row+",";
            }
            result.put("unAvailableOrgRow",unAvailableOrgRow.substring(0,unAvailableOrgRow.length()-1));
        }

        return result;
    }

    @Override
    @CacheEvict(value = "user",allEntries = true)
    @Transactional
    public Boolean batchDisableUsers(List<Long> userIdList) {
        User user = new User();
        user.setStatus(false);
        EntityWrapper<User> wrapper = new EntityWrapper<>();
        wrapper.in("user_id",userIdList);
        return super.update(user,wrapper);
    }

    @Override
    @CacheEvict(value = "user",allEntries = true)
    @Transactional
    public Boolean batchAbleUsers(List<Long> userIdList) {
        User user = new User();
        user.setStatus(true);
        EntityWrapper<User> wrapper = new EntityWrapper<>();
        wrapper.in("user_id",userIdList);
        return super.update(user,wrapper);
    }
}
